home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
strategy
/
vga_card.000
/
vga_cardgames-1.3.1.tar
/
vga_cardgames
/
klondike.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-05
|
7KB
|
389 lines
/*
* Klondike
*
* Copyright (C) Evan Harris, 1991, 1994
*
* Permission is granted to freely redistribute and modify this code,
* providing the author(s) get credit for having written it.
*/
#include <stdio.h>
#include <getopt.h>
#include "klondike.h"
unsigned char column[COLUMNS]; /* First card of column */
unsigned char stock, pile; /* First card of stock, pile */
short cards[NUMCARDS]; /* Positions of cards */
unsigned char next[NUMCARDS]; /* Card underneath */
unsigned char hidden[NUMCARDS]; /* Cards which are face down */
unsigned char foundation[NUMSUITS];
int stockcycled; /* The number of times stock has been cycled */
void main(int argc, char **argv)
{
short cmd, dest;
int cycle = 0, stockmove = 1;
int c, err = 0;
while ((c = getopt(argc, argv, "cm:")) != -1) {
switch (c) {
case 'c':
cycle = 1;
break;
case 'm':
stockmove = atoi(optarg);
if (stockmove == 0) {
err++;
}
break;
case '?':
err++;
break;
}
}
if (err) {
fprintf(stderr, "Usage: %s [-c] [-m N]", argv[0]);
fprintf(stderr, "\t-c cycle through stock forever\n");
fprintf(stderr, "\t-m N move through stock N cards at a time\n");
exit(1);
}
InitDisplay(argc, argv);
InitRandom(NEW);
Deal();
for (;;) {
cmd = GetCmd();
if (cmd == QUIT) {
EndDisplay();
exit(0);
}
else if (cmd == NEWGAME) {
InitRandom(NEW);
Deal();
}
else if (cmd == RESTART) {
InitRandom(LAST);
Deal();
}
else if (cmd == FROMSTOCK) {
FromStock(cycle, stockmove);
}
else if (ISCARD(NOHINT(cmd))) {
dest = FindDest(cmd);
if (dest != NOPOSN)
MakeMove((unsigned char)NOHINT(cmd), dest);
}
}
/* Never reached */
}
void Deal()
{
unsigned char i, j;
unsigned char row, col;
short r;
/* Initialise the deck */
for (i = 0; i < NUMCARDS; i++) {
cards[i] = NOPOSN;
next[i] = NOCARD;
}
for (i = 0; i < NUMSUITS; i++)
foundation[i] = ACE;
pile = NOCARD;
/* Deal the deck */
row = 0;
col = 0;
for (i = 0; i < NUMCARDS; i++) {
r = Random(NUMCARDS - i);
for (j = 0; j < NUMCARDS && r >= 0; j++) {
if (cards[j] == NOPOSN)
r--;
}
r = j - 1;
cards[r] = POSN(col, row);
if (col != STOCK) {
if (row == 0)
column[col] = r;
else {
for (j = 0; cards[j] != POSN(col, row - 1); j++)
;
next[j] = r;
}
if (col == row) {
hidden[r] = 0;
col++;
row = 0;
}
else {
hidden[r] = 1;
row++;
}
}
else {
if (row == 0)
stock = r;
else {
for (j = 0; cards[j] != POSN(col, row - 1); j++)
;
next[j] = r;
}
hidden[r] = 0;
row++;
}
}
stockcycled = 0;
for (i = 0; i < COLUMNS; i++)
DisplayColumn((short)i);
DisplayFoundations();
DisplayStockPile();
return;
}
short FindDest(short card)
{
unsigned char i, c;
short move;
if (HASHINT(card))
return FindHintedDest((short)NOHINT(card), (short)HINT(card));
move = CanMoveOff((unsigned char)card);
if (move == DESIRABLE)
return MOVEOFF;
if (TYPE(card) == KING) {
if (ROW(cards[card]) == 0 && COL(cards[card]) != PILE) {
if (move == POSSIBLE)
return MOVEOFF;
else
return NOPOSN;
}
for (i = 0; i < COLUMNS; i++)
if (column[i] == NOCARD)
return (short)POSN(i, 0);
}
else {
for (i = 0; i < COLUMNS; i++)
if (i != COL(cards[card]) && column[i] != NOCARD) {
c = column[i];
while (next[c] != NOCARD)
c = next[c];
if ((TYPE(c) == TYPE(card) + 1) &&
((ISBLACK(c) && ISRED(card)) ||
(ISRED(c) && ISBLACK(card)))) {
return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
}
}
}
if (move == POSSIBLE)
return MOVEOFF;
else
return NOPOSN;
}
short FindHintedDest(short card, short hint)
{
unsigned char c;
short move;
if (hint == FOUNDATION) {
move = CanMoveOff((unsigned char)card);
if (move != IMPOSSIBLE)
return MOVEOFF;
else
return NOPOSN;
}
if (TYPE(card) == KING) {
if (ROW(cards[card]) == 0 && COL(cards[card]) != PILE)
return NOPOSN;
if (column[hint] == NOCARD)
return (short)POSN(hint, 0);
}
else {
if (hint != COL(cards[card])) {
c = column[hint];
while (next[c] != NOCARD)
c = next[c];
if ((TYPE(c) == TYPE(card) + 1) &&
((ISBLACK(c) && ISRED(card)) ||
(ISRED(c) && ISBLACK(card))))
return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
}
}
return NOPOSN;
}
void MakeMove(unsigned char card, short dest)
{
short col, row, oldcol;
unsigned char c, i;
if (dest == MOVEOFF) {
MoveOff(card);
return;
}
col = COL(dest);
row = ROW(dest);
oldcol = -1;
if (pile == card) {
pile = next[card];
next[card] = NOCARD;
oldcol = PILE;
}
for (i = 0; oldcol == -1 && i < COLUMNS; i++) {
if (column[i] == card) {
column[i] = NOCARD;
oldcol = i;
}
}
for (i = 0; oldcol == -1 && i < NUMCARDS; i++) {
if (next[i] == card) {
if (hidden[i])
hidden[i] = 0;
next[i] = NOCARD;
oldcol = COL(cards[i]);
}
}
if (row > 0) {
c = column[col];
while (next[c] != NOCARD)
c = next[c];
next[c] = card;
}
else
column[col] = card;
while (card != NOCARD) {
cards[card] = POSN(col, row++);
card = next[card];
}
DisplayColumn(oldcol);
DisplayColumn(col);
return;
}
void FromStock(int cycle, int stockmove)
{
unsigned char oldpile, oldstock;
int i;
if (stock != NOCARD) {
for (i = 0; i < stockmove && stock != NOCARD; i++) {
oldpile = pile;
pile = stock;
stock = next[stock];
next[pile] = oldpile;
cards[pile] = POSN(PILE, 0);
}
DisplayStockPile();
} else if ((++stockcycled) / stockmove == 0 || cycle) {
while (pile != NOCARD) {
oldstock = stock;
stock = pile;
pile = next[pile];
next[stock] = oldstock;
cards[stock] = POSN(STOCK, 0);
hidden[stock] = 0;
}
DisplayStockPile();
}
return;
}
void MoveOff(unsigned char card)
{
unsigned char i;
short oldcol;
if (card == pile && TYPE(card) == foundation[SUIT(card)]) {
pile = next[card];
next[card] = NOCARD;
cards[card] = POSN(FOUNDATION, 0);
foundation[SUIT(card)]++;
DisplayFoundations();
DisplayStockPile();
}
else if (next[card] == NOCARD && TYPE(card) == foundation[SUIT(card)]) {
oldcol = -1;
for (i = 0; oldcol == -1 && i < COLUMNS; i++) {
if (column[i] == card) {
column[i] = NOCARD;
oldcol = i;
}
}
for (i = 0; oldcol == -1 && i < NUMCARDS; i++) {
if (next[i] == card) {
if (hidden[i])
hidden[i] = 0;
next[i] = NOCARD;
oldcol = COL(cards[i]);
}
}
cards[card] = POSN(FOUNDATION, 0);
foundation[SUIT(card)]++;
DisplayFoundations();
DisplayColumn((short)oldcol);
}
return;
}
short CanMoveOff(unsigned char card)
{
if (foundation[SUIT(card)] != TYPE(card) ||
(COL(cards[card]) != PILE && next[card] != NOCARD))
return IMPOSSIBLE;
if (LowestFoundation((unsigned char)SUIT(card)))
return DESIRABLE;
return POSSIBLE;
}
unsigned char LowestFoundation(unsigned char suit)
{
unsigned char i;
for (i = 0; i < NUMSUITS; i++)
if (foundation[i] < foundation[suit])
return FALSE;
return TRUE;
}